import pygame
import os
from pygame.locals import *
from OpenGL.GL import *

class WidgetCoord:
    
    def __init__(self, abs, rel=(0,0,0,0)):
        self.c = [0]*8
        self.t = [0]*4
        self.set_pos(abs[:2], rel[:2])
        self.set_size(abs[2:], rel[2:])
        self.validate_size()

    def set_pos(self, abs, rel=(0,0)):
        self.c[:2] = abs
        self.c[2:] = rel

    def set_size(self, abs, rel=(0,0)):
        self.c[4:6] = abs
        self.c[6:] = rel

    def set_x(self, abs, rel=0):
        self.c[0] = abs
        self.c[2] = rel

    def set_y(self, abs, rel=0):
        self.c[1] = abs
        self.c[3] = rel

    def set_width(self, abs, rel=0):
        self.c[4] = abs
        self.c[6] = rel

    def set_height(self, abs, rel=0):
        self.c[5] = abs
        self.c[7] = rel

    def validate_size(self, p=None):
        if p is None:
            s = self.size()
        else:
            s = p.pos.size()
            
        rel = (s[0] * self.c[2], s[1] * self.c[3], s[0] * self.c[6], s[1] * self.c[7])
        self.t[:] = self.c[0] + rel[0], self.c[1] + rel[1], self.c[4] + rel[2], self.c[5] + rel[3]
        
    def x(self):
        return self.t[0]
    
    def y(self):
        return self.t[1]

    def left(self):
        return self.t[0]

    def right(self):
        return self.t[0] + self.t[2]

    def top(self):
        return self.t[1]

    def bottom(self):
        return self.t[1] + self.t[3]
    
    def pos(self):
        return tuple(self.t[:2])
    
    def width(self):
        return self.t[2]
    
    def height(self):
        return self.t[3]
    
    def size(self):
        return tuple(self.t[2:4])

class Widget:
    """
    A widget is a base element of the gui system
    """
    def __init__(self, **args):

        self.widget_type = 'widget'

        args.setdefault("align",-1)
        args.setdefault("valign",-1)
        args.setdefault("zindex",1.)
        args.setdefault("padding", (0,0,0,0))
        args.setdefault("pos", WidgetCoord([0,0,1,1]))
        args.setdefault("color", (255,255,255,255))
        args.setdefault("font",pygame.font.SysFont("Tahoma", 16))

        self.pos = args["pos"]

        self.align = args["align"]
        self.valign = args["valign"]
        self.zindex = args["zindex"]
        self.padding = args["padding"]
        self.font = args["font"]
        self.color = args["color"]


        if "x" in args:
            self.pos.set_x(args["x"])
        if "y" in args:
            self.pos.set_y(args["y"])
        if "width" in args:
            self.pos.set_width(args["width"])
        if "height" in args:
            self.pos.set_height(args["height"])

        self.texture = None
        if "texture" in args:
            self.build_texture(args["texture"])

        self.parent = None

        self.enable = 1

        self.display_list = None
        self.surface = None

    def validate(self):
        self.pos.validate_size(self.parent)

    def set_parent(self, parent):
        self.pos.validate_size(parent)
        self.parent = parent

    def draw(self):
        if self.display_list is None:
            self.build_display()
                    
        glPushMatrix()
        #glLoadIdentity()
        #print 'draw gui widget'
        #set texture now so can have dynamic textures
        if self.texture:
            glBindTexture(GL_TEXTURE_2D, self.texture)
        glCallList(self.display_list)
        glPopMatrix()


    def event(self, event, ms):
        pass

    def update(self, ms):
        pass

    def build_display(self):
        l, t = self.pos.left() + self.padding[3], self.pos.top() + self.padding[0]
        r, b =  self.pos.right() - self.padding[1] , self.pos.bottom() - self.padding[2]
        z = self.zindex
        print l,t,r,b,z
        if self.texture is None:
            self.display_list = glGenLists(1)
            glNewList(self.display_list, GL_COMPILE)
            glDisable(GL_TEXTURE_2D)
            glDisable(GL_LIGHTING)
            glColor4d(*self.color)

            glBegin(GL_QUADS)
            
            glVertex3d(l, b, z)
            glVertex3d(r, b, z)
            glVertex3d(r, t, z)
            glVertex3d(l, t, z)
            glEnd()               

            glEndList()
        else:
            self.display_list = glGenLists(1)
            glNewList(self.display_list, GL_COMPILE)
            glEnable(GL_TEXTURE_2D)
            glEnable(GL_BLEND)
            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
            glColor3f(255,255,255)
            glBegin(GL_QUADS)

            glTexCoord2d(0.0,0.0)
            glVertex3d(l, b, z)
            glTexCoord2d(1.0,0.0)
            glVertex3d(r, b, z)
            glTexCoord2d(1.0,1.0)
            glVertex3d(r, t, z)
            glTexCoord2d(0.0,1.0)
            glVertex3d(l, t, z)
            glEnd()

            glDisable(GL_TEXTURE_2D)

            glEndList()


    def build_texture(self, path):
        
        #Load the image file
        fullpath = os.path.join('data', 'client', 'gui', 'images', path)
        self.surface = pygame.image.load(fullpath)
        #Convert it to load any alpha channel
        self.surface.convert_alpha()
        #Convert to PyOpenGL Data
        Data = pygame.image.tostring(self.surface, "RGBA", 1)
        #Select our Texture Object#Generate PyOpenGL Texture
        self.texture = glGenTextures(1)
        glBindTexture(GL_TEXTURE_2D, self.texture)
        #Load the Data into the Texture
        glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, self.surface.get_width(),
            self.surface.get_height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, Data )
        #Define some Parameters for this Texture
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST)
        glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)

    def redraw(self):
        self.display_list = None
        if self.parent is not None:
            self.parent.redraw()